package com.uni.db;

import com.uni.domain.Identifiable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.util.List;

public class GenericDaoImpl implements GenericDao {

    protected static Log log = LogFactory.getLog(GenericDaoImpl.class);

    @Autowired
    private SessionFactory sessionFactory;

    private Class entityClass;

    public Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    public Object get(Serializable id) {
        return getSession().get(getEntityClass(), id);
    }

    public Identifiable merge(Identifiable entity) {
        return (Identifiable) getSession().merge(entity);
    }

    public void save(Identifiable entity) {
        if (entity.isNew()) {
            getSession().saveOrUpdate(entity);
        } else {
            Object merged = getSession().merge(entity);
            getSession().saveOrUpdate(merged);
        }
    }

    public void delete(Identifiable entity) {
        getSession().delete(entity);
    }

    public List listAll() {
        return getSession().createCriteria(getEntityClass()).list();
    }

    public int countAll() {
        return ((Number) getSession().createCriteria(getEntityClass())
                .setProjection(Projections.count("id"))
                .uniqueResult()).intValue();
    }

    public int getMaxFieldVaue(String fieldName) {
        Number max = (Number) getSession().createCriteria(getEntityClass())
                .setProjection(Projections.max(fieldName))
                .uniqueResult();
        return max != null ? max.intValue() : 0;
    }


    public void evict(Identifiable obj) {
        getSession().evict(obj);
    }

    public void flushSession() {
        getSession().flush();
    }

    public void clearSession() {
        getSession().clear();
    }

    public void setEntityClass(Class entityClass) {
        this.entityClass = entityClass;
    }

    protected Class getEntityClass() {
        if (entityClass == null) {
            throw new IllegalStateException("You must set entityClass or override getEntityClass() method");
        }
        return entityClass;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

}
